﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.IO;
using Microsoft.Win32;
using DataSimDLL;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace BDSim
{
    /// <summary>
    /// LoadNavMsgDataWnd.xaml 的交互逻辑
    /// </summary>
    public partial class LoadNavMsgDataWnd : Window, INotifyPropertyChanged
    {
        public LoadNavMsgDataWnd()
        {
            InitializeComponent();
        }

        #region 成员及属性

        /// <summary>
        /// 界面选择卫星编号
        /// </summary>
        private ObservableCollection<SelectSat> selectNavData = new ObservableCollection<SelectSat>();

        public ObservableCollection<SelectSat> SelectNavData
        {
            get { return selectNavData; }
            set { selectNavData = value; NotifyPropertyChanged("SelectSP3Data"); }
        }

        /// <summary>
        /// 存储从导航电文文件中解析出来的星历转换得到的卫星PV
        /// </summary>
       public List<Dictionary<int, SatKeyInfo>> NavMsgPVList = new List<Dictionary<int, SatKeyInfo>>();

        ObservableCollection<NavMsgReport> _NavMsgReportList = new ObservableCollection<NavMsgReport>();

        /// <summary>
        /// 读取的所有导航电文分组集合
        /// </summary>
        public ObservableCollection<NavMsgReport> NavMsgReportList
        {
            get { return _NavMsgReportList; }
            set { _NavMsgReportList = value; NotifyPropertyChanged("NavMsgReportList"); }
        }

        int _SelectedIndex = -1;

        /// <summary>
        /// 当前选择的一组导航电文序号
        /// </summary>
        public int SelectedIndex
        {
            get { return _SelectedIndex; }
            set
            {
                _SelectedIndex = value; NotifyPropertyChanged("SelectedIndex");
                if (value >= 0)
                {
                    IsEnable = true;
                    selectNavData.Clear();
                    foreach (var item in NavMsgPVList[_SelectedIndex])
                    {
                        SelectSat temp = new SelectSat();
                        temp.IsChecked = true;
                        temp.PRN = item.Key;
                        temp.Name = item.Value.SysType + item.Key.ToString();
                        selectNavData.Add(temp);
                    }
                }
                else
                {
                    IsEnable = false;
                }


            }
        }

        private bool _IsEnable = false;
        /// <summary>
        /// 使能端口，绑定到导入卫星按钮，控制按钮是否可用状态
        /// </summary>
        public bool IsEnable
        {
            get { return _IsEnable; }
            set { _IsEnable = value; NotifyPropertyChanged("IsEnable"); }
        }
        /// <summary>
        /// 用户选择的时间
        /// </summary>
        public UTCTime SelectTime = new UTCTime();

        /// <summary>
        /// 环境段初始化后标识，导航电文时间与默认时间不一致，在转成ECF之前必须重新初始化环境段
        /// </summary>
        bool IsEnvInit = false;

        /// <summary>
        /// 实现INotifyPropertyChanged接口的成员
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        public void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion

        #region 执行打开导航电文文件
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            NavMsgPVList.Clear();
            NavMsgReportList.Clear();
            string currentDirectory = Directory.GetCurrentDirectory();
            OpenFileDialog OpenFile = new OpenFileDialog();
            OpenFile.Title = "选择Rinex导航电文文件";
            OpenFile.InitialDirectory = Directory.GetCurrentDirectory();
            //OpenFile.Filter = "导航电文文件(*.)|*.";
            string NavMsgDataPath = "path";
            if (OpenFile.ShowDialog() == true)
            {
                NavMsgDataPath = OpenFile.FileName;
                LoadState.Text = "正在读取";


                //  还原路径
                Directory.SetCurrentDirectory(currentDirectory);
                textBox1.Text = NavMsgDataPath;

                ///判断导航电文类型
                StreamReader sr = new StreamReader(NavMsgDataPath);
                string oneline = sr.ReadLine();
                char[] spilt = { ' ' };
                string[] data = oneline.Split(spilt, StringSplitOptions.RemoveEmptyEntries);
                int NavType = 2;//2表示V2.10, 3表示V3.02
                if (data[0] == "3.02")
                {
                    NavType = 3;
                }

                ///调用C++动态库读取电文文件
                RinexFileDLL.NavOpen(NavMsgDataPath.ToCharArray());
                int startIndex = 0;
                RinexFileDataType.NavMessage_Rinex NavMsg = new RinexFileDataType.NavMessage_Rinex();
                NodePosVel ECIPV = new NodePosVel();
                List<NodePosVel> PVList = new List<NodePosVel>();
                NavMsgPVList.Add(new Dictionary<int, SatKeyInfo>());
                RinexFileDataType.NavMessageHead NavMsgHead = new RinexFileDataType.NavMessageHead();
                int streamID = 1;
                int ReadFileFlag = 2;
                ///根据电文类型读导航电文头文件
                if (NavType == 2)
                {
                    ReadFileFlag = RinexFileDLL.NavReadHeader_V210(streamID, out NavMsgHead);
                }
                else if (NavType == 3)
                {
                    ReadFileFlag = RinexFileDLL.NavReadHeader_V302(streamID, out NavMsgHead);
                }

                List<UTCTime> TimeList = new List<UTCTime>();

                NavMsgReport NavMsgReport1 = new NavMsgReport();

                if (ReadFileFlag != 0)
                {
                    for (int Index = 0; Index < 32 * 12; Index++)
                    {
                        ///根据电文类型读一次文件
                        if (NavType == 2)
                        {
                            ReadFileFlag = RinexFileDLL.NavReadRecoder_V210(streamID, out NavMsg);
                        }
                        else if (NavType == 3)
                        {
                            ReadFileFlag = RinexFileDLL.NavReadRecoder_V302(streamID, out NavMsg);
                        }

                        ///表示已经读到文件末尾
                        if (ReadFileFlag == -1)
                        {
                            break;
                        }

                        ///读文件成功
                        else if (ReadFileFlag == 1)
                        {
                            ///根据电文转换成卫星位置速度
                            NavMesgData2PosVel(NavMsg, ref ECIPV);
                            if (NavType == 2)
                            {
                                if (Index > 0)
                                {
                                    ///如果当前时刻与上一刻时间相差大于300s，说明已经进入下一个时间段，重新计数
                                    if (Math.Abs(ECIPV.epoch.JD - PVList[0].epoch.JD) > 300.0 / 86400.0)
                                    {
                                        NavMsgReport1.Epoch = PVList[0].epoch;
                                        NavMsgReport1.Id += 1;
                                        NavMsgReport1.StartIndex = startIndex;
                                        NavMsgReportList.Add(NavMsgReport1);
                                        startIndex += PVList.Count;
                                        NavMsgReport1.EnableSatCount = 0;
                                        PVList.Clear();
                                        PVList.Add(ECIPV);
                                        NavMsgPVList.Add(new Dictionary<int, SatKeyInfo>());
                                    }
                                    else
                                    {
                                        PVList.Add(ECIPV);
                                    }
                                }
                                else
                                {
                                    PVList.Add(ECIPV);
                                }
                                ///把卫星信息添加到List当中
                                if (!NavMsgPVList[NavMsgPVList.Count - 1].Keys.Contains(NavMsg.PRN))
                                {
                                    SatKeyInfo newSatKeyInfo = new SatKeyInfo() { SatIndex = NavMsg.PRN, a0 = NavMsg.a0, a1 = NavMsg.a1, a2 = NavMsg.a2, SatPV = ECIPV, SysType = NavMsgHead.SysType };
                                    NavMsgPVList[NavMsgPVList.Count - 1].Add(NavMsg.PRN, newSatKeyInfo);
                                    NavMsgReport1.EnableSatCount++;
                                }
                            }
                            else if (NavType == 3)
                            {
                                ///如果时间列表中不包含当然时间，则添加
                                if (!TimeList.Contains(ECIPV.epoch))
                                {
                                    TimeList.Add(ECIPV.epoch);

                                    ///新的时间段添加一个
                                    if (Index > 0)
                                    {
                                        NavMsgPVList.Add(new Dictionary<int, SatKeyInfo>());
                                    }
                                    ///新的时间段添加，且卫星计数归零
                                    NavMsgReport1.EnableSatCount = 0;
                                    NavMsgReportList.Add(NavMsgReport1);
                                }

                                ///判断当前卫星属于哪个时间段列表
                                int ListIndex = 0;
                                for (int i = 0; i < NavMsgPVList.Count; i++)
                                {
                                    if (NavMsgPVList[i].Count > 0)
                                    {
                                        foreach (var item in NavMsgPVList[i])
                                        {
                                            ///防止时间转换中的一些误差
                                            if (Math.Abs(ECIPV.epoch.JD - item.Value.SatPV.Epoch.JD) < 0.01 / 86400.0)
                                            {
                                                ListIndex = i;
                                                break;
                                            }
                                        }
                                    }
                                    else if (NavMsgPVList[i].Count == 0)
                                    {
                                        ListIndex = i;
                                        break;
                                    }
                                }

                                ///把当前的卫星信息添加到对应列表的字典中
                                if (!NavMsgPVList[ListIndex].Keys.Contains(NavMsg.PRN))
                                {
                                    SatKeyInfo newSatKeyInfo = new SatKeyInfo() { SatIndex = NavMsg.PRN, a0 = NavMsg.a0, a1 = NavMsg.a1, a2 = NavMsg.a2, SatPV = ECIPV, SysType = NavMsg.SysType };
                                    NavMsgPVList[ListIndex].Add(NavMsg.PRN, newSatKeyInfo);
                                    NavMsgReport1 = NavMsgReportList[ListIndex];
                                    NavMsgReport1.Epoch = ECIPV.Epoch;
                                    NavMsgReport1.EnableSatCount++;
                                    NavMsgReport1.Id = ListIndex + 1;
                                    NavMsgReportList[ListIndex] = NavMsgReport1;
                                }
                            }
                        }
                        else
                        {
                            MessageBox.Show("导航电文数据打开失败！");
                        }
                    }
                    LoadState.Text = "读取完毕";
                }
                else
                {
                    MessageBox.Show("导航电文数据打开失败！");
                }
                SelectedIndex = -1;
                RinexFileDLL.NavClose(1);
            }
        }
        #endregion

        #region 导航电文转ECIPV
        /// <summary>
        /// 导航电文数据转ECIPV
        /// </summary>
        /// <param name="NavMsg">导航电文数据</param>
        /// <param name="ECIPV">卫星轨道，ECI</param>
        unsafe public void NavMesgData2PosVel(RinexFileDataType.NavMessage_Rinex NavMsg, ref NodePosVel ECIPV)
        {
            Ephemeris_16 Eph_Param16 = new Ephemeris_16();
            Eph_Param16.LoadDataFromRinexNavMsg(NavMsg);

            ///根据选择的历元重新读取极移文件
            if (!IsEnvInit)
            {
                UTCTime EopEnd = Eph_Param16.t;
                EopEnd.JD = EopEnd.JD + 1;
                TimeSpaceDll.CAL2UTC(out EopEnd, 2);

                string FileName = Directory.GetCurrentDirectory() + "\\ConfigFiles\\EOP_BDSim.txt";
                bool ret = BDSim.ReadEOP.EOP_Init(FileName.ToCharArray(), Eph_Param16.t, EopEnd);
                if (ret == true)
                {
                    int count = 0;
                    EOPData* pdata = BDSim.ReadEOP.EOP_GetEopData(out count);
                    //时空类动态库初始化
                    BDSim.TimeSpaceDll.TimeSpaceInit(pdata, count);
                }
                else
                {
                    MessageBox.Show("读极移跳秒文件失败！", "错误");
                }
                IsEnvInit = true;
            }
            Eph_Param16.toe = NavMsg.TOE_3;

            int SatFlag = 1;//非GEO卫星
            if (Eph_Param16.i < 10*Math.PI/180.0)
            {
                SatFlag = 2;  //GEO卫星
            }

            int bIner = 1;//惯性系PV
            EphemerisDLL.CalNav16ToPV(Eph_Param16, SatFlag, NavMsg.TOE_3, out ECIPV, bIner);

        }


        #endregion


        #region 执行导入卫星
        private void button3_Click(object sender, RoutedEventArgs e)
        {
            LoadState.Text = "正在导入";
            if (NavMsgPVList.Count != 0 && SelectedIndex >= 0)
            {   
                this.DialogResult = true;
            }
            else
            {
                MessageBox.Show("没有导入数据或没有选择项!");
            }
        }
        #endregion

        #region 关闭窗口
        private void button2_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = false;
        }
        #endregion
    }

    /// <summary>
    /// 加载导航电文窗口报告
    /// </summary>
    public struct NavMsgReport
    {
        public int Id { get; set; }
        public UTCTime Epoch { get; set; }
        public int EnableSatCount { get; set; }
        public int StartIndex { get; set; }
    }

    public struct SatKeyInfo
    {
        public int SatIndex;
        public NodePosVel SatPV;
        public double a0;
        public double a1;
        public double a2;
        //卫星系统标识
        public char SysType;
    }
}
